from blinker import Device
from machine import Timer, Pin, I2C, WDT
import esp
import time
import json
import random
import math
from aht20 import AHT20
from bmp280 import BMP280
# import wifimgr # 这个模块耗电大，会引起系统重启


authKey = '7c20ab675350'
ssid = "jxlab1"
password = "sfzx334wf"

# ssid = "CMCC-r7hn"
# password = "u5xykjk9"
# p2 = Pin(2, Pin.OUT)
# p2.value(1)
# cnt = 0
startTime = time.ticks_ms()
uptime_s = 0

# 创建I2C对象
i2c = I2C(scl=Pin(2), sda=Pin(0), freq=100000)

# 传感器地址
AHT20_ADDR = 0x38
BMP280_ADDR = 0x77

# 中断回调函数的形参必须要有一个,没有也要添加self作为实参来传递
# def timer_callback(self):
#     global cnt #声明为全局变量
#     
#     cnt += 1
#     print("天气实况采集了 "+str(cnt)+" 次")
#     wxGet.wxget()


# 中断回调函数的形参必须要有一个,没有也要添加self作为实参来传递
# WIFI断网重连
# def timer_callback(self):
#     global light
#     
#     if not station.isconnected():
#         print("WIFI connecting...") 
#         station.connect(ssid, password)
#     light = not light
#     p2.value(light)


# if station.isconnected() == True:
#     print("WIFI Already connected!")
#     print(station.ifconfig())
# else:
#     station.active(True)
#     station.connect(ssid, password)
#     print("WIFI connecting...")        
#     while (station.isconnected() == False):
#          time.sleep_ms(50)
#     print(station.ifconfig())
# 调研配网模块
# wlan = wifimgr.get_connection()
# if wlan is None:
#     print("Could not initialize the network connection.")

# Main Code goes here, wlan is a working network.WLAN(STA_IF) instance.
# print("ESP WiFi is OK")
# print(time.localtime())
# rtc = RTC()
# ntptime.host = 'ntp.aliyun.com'
# while True:
#     try:
#         ntptime.settime()
#         break
#     except:
#         print("NTP连接网络超时")
#         time.sleep(5)
#         continue
# utc_time = ntptime.time()
# local_time = time.gmtime(utc_time + 28800) #东8区增加8*60*60秒
# rtc.datetime((local_time[0],local_time[1],local_time[2],
#               local_time[6],local_time[3],local_time[4],
#               local_time[6],0))
# print(time.localtime())
# print("*" * 20)

# 中断回调函数的形参必须要有一个,没有也要添加self作为实参来传递
my_timer = Timer(-1) # -1 的 ID 构造一个虚拟计时器
timer_cnt = 0 # 定时器中断计数
offline_cnt = 0 # 掉线次数
th = 0
humidity=0.0
temperature=0.0
pressure = 0.0

def timer_callback(self):
    global humidity
    global temperature
    global pressure
    global timer_cnt
    global offline_cnt
    
    temperature = aht.temperature
    humidity = aht.humidity
    tmp = bmp.temperature # 测气压前先测温，用于补偿
    pressure = bmp.pressure
    
    if sensor.isconnect == 0:
        offline_cnt += 1
        if offline_cnt > 4:
            with open("log.txt", 'a') as log:
                current_time = time.localtime()[:6]
                formatted_time = '{}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}'.format(
                                current_time[0], current_time[1], current_time[2],
                                current_time[3], current_time[4], current_time[5])
                log.write("Offline out timer!Machine reset. #{0}\n".format(formatted_time))
                my_timer.deinit()
            machine.reset()
    else:
        offline_cnt = 0
        
    timer_cnt += 1
    if timer_cnt >= 5:
        timer_cnt = 0
        if (not humidity == None):
            stor_data = {"d1": round(temperature, 1), "d2": round(humidity, 1)}
            sensor.dataStore(stor_data)

def seconds_to_days(seconds):
    days = int(seconds // (24 * 3600)) # 计算天数
    hours = int((seconds % (24 * 3600)) // 3600)  # 计算小时数
    minutes = int((seconds % 3600) // 60 ) # 计算分钟数
    seconds = int(seconds % 60 ) # 计算剩余秒数
    return days, hours, minutes, seconds

def sub_callback(topic, message):
    global startTime
    global uptime_s
    global humidity
    global temperature
    global pressure
    
    raw = message.decode()
    print("收到消息:", raw)    
    rcv = json.loads(raw)
    if rcv.get("data").get("get") == "state":
        nowTime = time.ticks_ms()
        uptime_s += time.ticks_diff(nowTime, startTime)/1000
        startTime = nowTime
        days, hours, minutes, seconds = seconds_to_days(uptime_s)        
        rssi = sensor.wifiRssi
        if rssi >= -50:
            signal = "fas fa-signal"
        elif rssi >= -62:
            signal = "fas fa-signal-4"
        elif rssi >= -74:
            signal = "fas fa-signal-3"
        elif rssi >= -82:
            signal = "fas fa-signal-2"
        elif rssi >= -92:
            signal = "fas fa-signal-1"
        else:
            signal = "fas fa-signal-slash"
        
        tim =  time.localtime()
        state = {"state":"online"}
        tex_tim = {"tex-tim": {"tex": '{0:02d}:{1:02d}:{2:02d}'.format(tim[3],tim[4],tim[5])}}
        tex_hdf = {"tex-hdf": {"tex": f'{days}天{hours}小时{minutes}分{seconds}秒'}}
        num_tmp = {"num-tmp": {"val": round(temperature, 1)}}
        num_hum = {"num-hum": {"val": round(humidity, 1)}}
        num_abc = {"num-abc": {"val": rssi, "ico": signal}}
        num_762 = {"num-762": {"val": round(pressure)}}
        state.update(tex_hdf)
        state.update(num_tmp)
        state.update(num_hum)
        state.update(num_abc)
        state.update(num_762)
        state.update(tex_tim)
        sensor.send(state)
        print("发送消息:", state)
    elif rcv.get("data").get("btn-abc") == "on":
        btn_abc = {"btn-abc": {"swi": "on", "ico": "fad fa-siren-on", "clr": "#EA0909"}}
        sensor.send(btn_abc)
        print("发送消息:", btn_abc)
#         p2.value(0)
    elif rcv.get("data").get("btn-abc") == "off":
        btn_abc = {"btn-abc": {"swi": "off", "ico": "fad fa-siren", "clr": "#595959"}}
        sensor.send(btn_abc)
        print("发送消息:", btn_abc)
#         p2.value(1)
    elif rcv.get("data").get("btn-123") == "tap":
        btn_123_cnt += 1
        num_abc = {"num-abc": {"val": btn_123_cnt}}
        sensor.send(num_abc)
        print("发送消息:", num_abc)
    else:
        pass

if __name__ == '__main__':     
    sensor = Device(sub_callback)
    rt = sensor.begin(authKey, ssid, password)
    if rt != 0:
        print("MQTT connect error.")
        machine.reset()
    # while sensor.isconnect == 0: #等待mqtt连接成功
        # pass
#     esp.sleep_type(esp.SLEEP_LIGHT) # 设置休眠方式

    bmp = BMP280(i2c, BMP280_ADDR) # 创建BMP280对象 
    aht = AHT20(i2c, AHT20_ADDR) # 创建AHT20对象
    temperature = aht.temperature
    humidity = aht.humidity
    tmp = bmp.temperature # 测气压前先测温，用于补偿
    pressure = bmp.pressure
    my_timer.init(period = 60000,
                mode = Timer.PERIODIC,
                callback = timer_callback)
    #wdt = machine.WDT(timeout=5000)  # 设置看门狗定时器超时时间为5秒    
    try:
        while True:    
            sensor.run()
            #wdt.feed()  # 喂狗，重置看门狗定时器
            time.sleep_ms(101)
    except KeyboardInterrupt:
        print("\n按下Ctrl + C中断程序...\n")
        sensor.disconnect()
        my_timer.deinit()
    except Exception as err:
        print("发生异常:", err)
        with open("log.txt", 'a') as log:
            current_time = time.localtime()[:6]
            formatted_time = '{}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}'.format(
                current_time[0], current_time[1], current_time[2],
                current_time[3], current_time[4], current_time[5])
            log.write("发生异常:{0}.".format(err))
            log.write(" #{0}\n".format(formatted_time))
            my_timer.deinit()
        machine.reset()
